<template>
  <div class="attribute-lay" v-loading="loading">
    <el-form ref="refForm" v-if="hasData" label-width="120" :model="attributes">
      <el-form-item v-for="(item, index) in attributes" :prop="'attributes.' + index + '.name'" :key="item.id" :label="item.label"
                    :rules="{validator: (e1: any, e2: any, e3: any) => validLabelValue(e1, e2, e3, item), required: item.isRequired, trigger: 'blur'}">
        <!-- 根据模型数据定义动态显示需要编辑的属性 -->
        <el-select class="attribute-item" v-model="item.value" :fit-input-width="true" v-if="item.mode == 'select'">
          <el-option
                v-for="option in item.options"
                :key="option.name"
                :label="option.name"
                :value="option.value"
            />
        </el-select>
        <el-checkbox-group class="attribute-item" v-model="item.value" v-else-if="item.mode == 'check-box'" >
          <el-checkbox v-for="(di) in item.options" :key="di.name" :label="di.value">
            {{ di.name }}
          </el-checkbox>
        </el-checkbox-group>
        <el-checkbox class="attribute-item" v-model="item.value" v-else-if="item.type=='bool'" />
        <el-radio-group class="attribute-item" v-model="item.value" v-else-if="item.mode == 'radio-box'" >
          <el-radio v-for="(di) in item.options" :key="di.name" :label="di.value">
            {{ di.name }}
          </el-radio>
        </el-radio-group>
        <el-input class="attribute-item" v-else :readonly="props.readOnly" v-model="item.value"
                  @input="() => checkLabelValue(item)" />
      </el-form-item>
    </el-form>
    <div v-if="!hasData" style="display: flex; flex-direction: column; align-items: center; ">
      <div style="max-width: 680px" v-if="!props.readOnly">
        当前没有定义任何属性，请先配置属性数据模型再刷新。
      </div>
      <div style="max-width: 680px" v-if="props.readOnly">
        当前没有任何属性，请点击下方按钮再次刷新。
      </div>
      <div style="display: flex; flex-direction: row;">
        <el-button class="attribute-add" plain icon="Refresh" text @click="refresh">
          刷新
        </el-button>
      </div>
    </div>

    <div class="attribute-actions" v-if="hasData">
      <el-button v-if="!props.readOnly" type="primary" style="padding: 0 16px" icon="Check"
                 @click="saveAttribute(false)">
        保存
      </el-button>
      <el-button plain icon="Refresh" text @click="refreshAttribute">
        刷新
      </el-button>
    </div>
  </div>
</template>

<script setup lang="ts">

import {nextTick, ref} from "vue";
import {loadAttributeOfAsset, queryAssetLabels, saveAttributeOfAsset} from "@/apis/sop";
import {useCurrent} from "@/utils/sop/UseCurrentFunc";
import {msgError, msgInfo, msgWarn} from "@/utils/InfoUtil";
import {runMethod} from "@/utils/DateUtil";
import {SERVERS} from "@/stores/conf";
import {useStore} from "@/stores";
import {checkDoubleValue, checkLongValue} from "@/utils/StrUtil";

const store = useStore();
const hasData = ref();
const loading = ref(false);
const refForm = ref();

// 保存资源对应的数据模型文件
const attributes = ref<any>([]);

const props = withDefaults(defineProps<{
  entry: any,
  loadAttr?: any,
  saveAttr?: any,
  deleteAttr?: any,
  readOnly?: any,
  hideKeys?: any,
  targetId?: string,
}>(), {
  hideKeys: []
});

const modelPlatformId = ref(import.meta.env.VITE_APP_PLATFORM);
const {current} = useCurrent(props.entry.name);

const getTargetId = () => {
  if (props.targetId) {
    return props.targetId;
  }
  if (SERVERS.REALM === props.entry.server) {
    return store.getCurrentRealms().id;
  } else {
    return store.getCurrentPlatform().id;
  }
}

const checkLabelValue = (item: any) => {
  if (item.value) {
    if ('long' == item.type) {
      item.value = checkLongValue(item.value);
    } else if ('double' == item.type) {
      item.value = checkDoubleValue(item.value);
    }
  }
}

const validLabelValue = (rule: any, value: any, callback: any, item: any) => {
  if (!item.value) {
    if (item.isRequired) {
      callback(new Error(`${item.label}不能为空`));
    } else {
      callback();
    }
  } else if(!item.checkRule) {
    callback();
  } else {
    try {
      const reg = new RegExp(item.checkRule);
      if (!reg.test(item.value)) {
        callback(new Error(item.checkRuleTip || '请输入正确的值'));
      } else {
        callback();
      }
    } catch (error) {
      callback();
    }
  }
}

const convertValueToShow = (type: string, val: any) => {
  if ('long' == type) {
    return val;
  } else if ('double' == type) {
    return val;
  } else if ('string' == type) {
    return val;
  } else if ('bool' == type) {
    return val == true || 'true' == val || val;
  }
}

const objectToAttribute = (objs: any, tag: string) => {
  attributes.value.forEach((item: any) => {
    const val: any = objs[item.name];
    item.isRequired = !!item.isRequired;

    if (val != undefined) {
      item.value = convertValueToShow(item.type, val);
    } else {
      item.value = convertValueToShow(item.type, item.defValue);
      if (item.value == undefined) {
        if (item.mode == 'check-box') {
          item.value = [];
        } else {
          item.value = '';
        }
      }
    }
    item.tag = tag;
  })
  hasData.value = attributes.value?.length > 0;
}

const checkIsSave = () => {
  let ok: boolean = true;
  if (attributes.value && attributes.value.length !== 0) {
    for (let i = 0; i < attributes.value.length; ++i) {
      const item = attributes.value[i];
      if (!item.tag) {
        ok = false;
        break;
      }
    }
  }
  return ok;
}

const checkAttribute = () => {
  let ok: boolean = true;
  if (attributes.value && attributes.value.length !== 0) {
    for (let i = 0; i < attributes.value.length; ++i) {
      const item: any = attributes.value[i];
      if (item.isRequired && item.value == undefined) {
        ok = false;
        msgWarn('请输入Value的值！');
        break;
      }
    }
  }

  return ok;
}

const attributeToObject = () => {
  let obj: any = {};
  if (attributes.value && attributes.value.length !== 0) {
    attributes.value.forEach((item: any) => {
      if (item.name && item.value != undefined) {
        obj[item.name] = item.value;
      }
    })
  }
  return obj;
}

const readAssetAttr = async (params: any) => {
  if (props.loadAttr) {
    return await props.loadAttr({
      server: props.entry.server,
      targetId: getTargetId(),
      ...params
    });
  } else {
    return await loadAttributeOfAsset({
      server: props.entry.server,
      targetId: getTargetId(),
      ...params
    });
  }
}

const saveAssetAttr = async (params: any) => {
  if (props.saveAttr) {
    return await props.saveAttr({
      server: props.entry.server,
      targetId: getTargetId(),
      ...params
    });
  } else {
    return await saveAttributeOfAsset({
      server: props.entry.server,
      targetId: getTargetId(),
      ...params
    });
  }
}

/**
 * 载入资源的模型文件
 */
const loadAssetModel = async () => {
  return await queryAssetLabels({
    platformId: modelPlatformId.value,
    assetType: props.entry.type,
  });
}

/**
 * 加载资源的属性信息
 * @param setHasData 是否需要初始化是否有数据标志
 */
const reloadAttr = async (setHasData: any) => {
  const retModel: any = await loadAssetModel();
  attributes.value = retModel.data || [];

  if (attributes.value.length > 0) {
    const result = await readAssetAttr({
      assetId: current().id,
      assetType: props.entry.type,
    });
    objectToAttribute(result.data || [], 'save');
  } else if (retModel) {
    if (setHasData) {
      hasData.value = false;
    }
    if (retModel.code !== 0) {
      msgError(retModel.message || '加载属性失败');
    }
  } else if (setHasData) {
    hasData.value = false;
  }
}

const doRefresh = async (setHasData: any) => {
  loading.value = true;
  await runMethod({}, async () => {
    await reloadAttr(setHasData);
  });
  loading.value = false;
}

const refresh = async () => {
  if (hasData.value) {
    await doRefresh(true);
  } else {
    hasData.value = true;
    await nextTick(async () => await doRefresh(true));
  }
}

const refreshAttribute = async () => {
  if (!checkIsSave()) {
    msgWarn('当前存在未保存的属性！')
  } else {
    await doRefresh(false);
  }
}

const saveAttribute = async (setHasData: any) => {
  if (await refForm.value.validate()) {
    if (!checkAttribute()) {
      return;
    }
    const obj = attributeToObject();
    loading.value = true;
    await runMethod({}, async () => {
      const result = await saveAssetAttr({
        assetId: current().id,
        assetType: props.entry.type,
        props: {...obj},
      });
      if (result && result.code === 0) {
        await reloadAttr(setHasData);
        msgInfo('保存属性成功');
      } else if (result) {
        msgError(result.message);
      }
    });
    loading.value = false;
  }
}

defineExpose({
  refresh,
})

</script>

<style scoped>
.attribute-lay {
  display: flex;
  flex-direction: column;
  color: #252A2F;
  padding: 8px 16px;
  flex: 1;
}

.attribute-item {
  max-width: 800px;
}

.attribute-add {
  margin: 32px 0;
}

.attribute-actions {
  display: flex;
  flex-direction: row;
  margin: 16px 0 16px 48px;
}

</style>
